
/************************************************************************************************* 

	Name: IR_C
	Autor: JA&AP
	
	Contains: 
				File containing all the functions related to the IRSensors hardware.
				
				
**************************************************************************************************/


#include <avr/io.h>
#include <avr/interrupt.h>

#include "ir.h"

//RECEPTOR 80N
#define DDR_IR_R_80N DDRE
#define PORT_IR_R_80N PORTE
#define PORTPIN_IR_R_80N PINE
#define PIN_IR_R_80N PE2

//RECEPTOR 45N
#define DDR_IR_R_45N DDRE
#define PORT_IR_R_45N PORTE
#define PORTPIN_IR_R_45N PINE
#define PIN_IR_R_45N PE4

//RECEPTOR 10N
#define DDR_IR_R_10N DDRE
#define PORT_IR_R_10N PORTE
#define PORTPIN_IR_R_10N PINE
#define PIN_IR_R_10N PE7

//RECEPTOR 10P
#define DDR_IR_R_10P DDRB
#define PORT_IR_R_10P PORTB
#define PORTPIN_IR_R_10P PINB
#define PIN_IR_R_10P PB5

//RECEPTOR 45P
#define DDR_IR_R_45P DDRD
#define PORT_IR_R_45P PORTD
#define PORTPIN_IR_R_45P PIND
#define PIN_IR_R_45P PD0

//RECEPTOR 80P
#define DDR_IR_R_80P DDRD
#define PORT_IR_R_80P PORTD
#define PORTPIN_IR_R_80P PIND
#define PIN_IR_R_80P PD4

//EMITTER 80N
#define DDR_IR_E_80N DDRE
#define PORT_IR_E_80N PORTE
#define PIN_IR_E_80N PE3

//EMITTER 45N
#define DDR_IR_E_45N DDRE
#define PORT_IR_E_45N PORTE
#define PIN_IR_E_45N PE5

//EMITTER 10N
#define DDR_IR_E_10N DDRB
#define PORT_IR_E_10N PORTB
#define PIN_IR_E_10N PB0

//EMITTER 10P
#define DDR_IR_E_10P DDRB
#define PORT_IR_E_10P PORTB
#define PIN_IR_E_10P PB6

//EMITTER 45P
#define DDR_IR_E_45P DDRD
#define PORT_IR_E_45P PORTD
#define PIN_IR_E_45P PD1

//EMITTER 80P
#define DDR_IR_E_80P DDRD
#define PORT_IR_E_80P PORTD
#define PIN_IR_E_80P PD5

//Period of IR signal (1600 us)
#define PERIOD_IR F_CPU/625
//Period of LOW IR Signal (1000 us)
#define PERIOD_IR_LOW F_CPU/1000

//defines which IRs are active
static volatile unsigned char activeIRs;
//defines the actual IR being readed
static volatile unsigned char actualPollIR;
//saves the state of the IRs
static volatile unsigned char actualStateIRs;


static void ir_enable(unsigned char ir,unsigned char en);

//Configura pines de entrada para los receptores, y de salida para los emisores
void ir_init(void){

	//Setting IR Receptor Pins as input
	DDR_IR_R_80N   &= ~(1<<PIN_IR_R_80N);
	DDR_IR_R_45N &= ~(1<<PIN_IR_R_45N);
	DDR_IR_R_10N &= ~(1<<PIN_IR_R_10N);
	DDR_IR_R_10P &= ~(1<<PIN_IR_R_10P);
	DDR_IR_R_45P &= ~(1<<PIN_IR_R_45P);
	DDR_IR_R_80P &= ~(1<<PIN_IR_R_80P);
	
	//Setting IR Emitter Pins as output	
	DDR_IR_E_80N |= (1<<PIN_IR_E_80N);
	DDR_IR_E_45N |= (1<<PIN_IR_E_45N);
	DDR_IR_E_10N |= (1<<PIN_IR_E_10N);
	DDR_IR_E_10P |= (1<<PIN_IR_E_10P);
	DDR_IR_E_45P |= (1<<PIN_IR_E_45P);
	DDR_IR_E_80P |= (1<<PIN_IR_E_80P);
	
	//Setting emitters in High Output
	ir_enable(IR_80N,OFF);
	ir_enable(IR_45N,OFF);
	ir_enable(IR_10N,OFF);
	ir_enable(IR_10P,OFF);
	ir_enable(IR_45P,OFF);
	ir_enable(IR_80P,OFF);
	
	//configure timer 5 in order to generate appropiate frequency for the Emitters.
	//CTC Mode, No prescaling
	TCCR5B |= (1<<WGM52) | (1<<CS50);
	//TODO: COMENTAR BIEN COMO SE CALCULA!!#define PERIOD_IR F_CPU/625

	OCR5A = PERIOD_IR;
	
	OCR5B = PERIOD_IR_LOW;
}

//Pone un uno o un cero en el respectivo pin de ir, dependiendo del valor de en
static void ir_enable(unsigned char ir,unsigned char en){

	
	switch(ir){
		case IR_80N:
			if(en)
				PORT_IR_E_80N |= (1<<PIN_IR_E_80N);
			else
				PORT_IR_E_80N &= ~(1<<PIN_IR_E_80N);
		break;
		case IR_45N:
			if(en)
				PORT_IR_E_45N |= (1<<PIN_IR_E_45N);
			else
				PORT_IR_E_45N &= ~(1<<PIN_IR_E_45N);
		break;
		case IR_10N:
			if(en)
				PORT_IR_E_10N |= (1<<PIN_IR_E_10N);
			else
				PORT_IR_E_10N &= ~(1<<PIN_IR_E_10N);
		break;
		case IR_10P:
			if(en)
				PORT_IR_E_10P |= (1<<PIN_IR_E_10P);
			else
				PORT_IR_E_10P &= ~(1<<PIN_IR_E_10P);
		break;
		case IR_45P:
			if(en)
				PORT_IR_E_45P |= (1<<PIN_IR_E_45P);
			else
				PORT_IR_E_45P &= ~(1<<PIN_IR_E_45P);
		break;
		
		case IR_80P:
			if(en)
				PORT_IR_E_80P |= (1<<PIN_IR_E_80P);
			else
				PORT_IR_E_80P &= ~(1<<PIN_IR_E_80P);
		break;
		default:
		break;

	}
}

void ir_activate(unsigned char ir,unsigned char en)
{
	if(en)
	{
		activeIRs |= (1<<ir);
		//activate interrupts
		TIMSK5 |= (1<<OCIE5A) | (1<<OCIE5B);
	}
	else
		activeIRs &= ~(1<<ir);
	
	//disable timer interrupt
	if(!activeIRs)
		TIMSK5 &= ~(1<<OCIE5A) & ~(1<<OCIE5B);
}
void ir_activateAll(unsigned char en)
{
	if(en)
	{
		activeIRs = 0x3F;
		//activate timer interrupts
		TIMSK5 |= (1<<OCIE5A) | (1<<OCIE5B);
	}
	else
	{
		activeIRs = 0;
		TIMSK5 &= ~(1<<OCIE5A) & ~(1<<OCIE5B);
	}
	
}
//Lee el valor del pin de ir, aplicando una mascara, y luego haciendo el respectivo corrimiento para que elvalor devuelto sea 0 o 1.
//OJO: Devuelve ON u OFF.
static unsigned char ir_getState(unsigned char ir){
	
	switch(ir){
		case IR_80N:
			return !((PORTPIN_IR_R_80N & (1<<PIN_IR_R_80N))>>PIN_IR_R_80N);
		break;
		case IR_45N:
			return !((PORTPIN_IR_R_45N & (1<<PIN_IR_R_45N))>>PIN_IR_R_45N);
		break;
		case IR_10N:
			return !((PORTPIN_IR_R_10N & (1<<PIN_IR_R_10N))>>PIN_IR_R_10N);
		break;
		case IR_10P:
			return !((PORTPIN_IR_R_10P & (1<<PIN_IR_R_10P))>>PIN_IR_R_10P);
		break;
		case IR_45P:
			return !((PORTPIN_IR_R_45P & (1<<PIN_IR_R_45P))>>PIN_IR_R_45P);
		break;
		case IR_80P:
			return !((PORTPIN_IR_R_80P & (1<<PIN_IR_R_80P))>>PIN_IR_R_80P);
		break;
		default:
			return 0;
		break;

	}

}

unsigned char ir_read()
{
	return actualStateIRs;
}
//TODO: falta poder definir cuales IR deberian estar activos.

//todo el ciclo.
ISR(TIMER5_COMPA_vect)
{
	if(actualPollIR == IR_80P)
		actualPollIR = IR_80N;
	else
		actualPollIR++;
	
	ir_enable(actualPollIR,OFF);
}
//tiempo en que la señal de apagada debe cambiar a encendida.
ISR(TIMER5_COMPB_vect)
{
	
	//get state of receiver. if its ON, write 1 in state of IRs (actualStateIRs variable)
	if(ir_getState(actualPollIR))
		actualStateIRs |= (1<<actualPollIR);
	else
		actualStateIRs &= ~(1<<actualPollIR);
	
	ir_enable(actualPollIR,ON);
}



